package own.stu.jobgib.playown.vediodown.common.service;

import org.apache.commons.collections.CollectionUtils;
import own.stu.jobgib.playown.vediodown.common.config.DefaultConfig;
import own.stu.jobgib.playown.vediodown.common.model.BaseDataInfo;
import own.stu.jobgib.playown.vediodown.common.model.ItemFilter;
import own.stu.jobgib.playown.vediodown.common.model.SimpleMediaItem;

import java.util.ArrayList;
import java.util.List;
import java.util.function.Function;
import java.util.function.Supplier;

public class ItemQueryService extends CommonService {

    private CacheItemService cacheItemService;
    private QueueService queueService;
    private BaseDownloadService downLoadService;

    public ItemQueryService(DefaultConfig cfg, QueueService queueService, BaseDownloadService downLoadService) {
        super(cfg);
        cacheItemService = new CacheItemService(cfg);
        this.queueService = queueService;
        this.downLoadService = downLoadService;
    }

    public <M, P, T extends BaseDataInfo<M, P>> List<SimpleMediaItem> getItemList(String url, Class<T> clazz, Supplier<String> cookiesSupplier) {
        return getItemList(url, true, clazz, cookiesSupplier);
    }

    public <M, P, T extends BaseDataInfo<M, P>> List<SimpleMediaItem> getItemList(String url, boolean withNext, Class<T> clazz, Supplier<String> cookiesSupplier) {

        try {
            T content = get(url,
                    cookiesSupplier.get(),
                    clazz);
            List<M> itemList = content.getItemList();
            if (CollectionUtils.isEmpty(itemList)) {
                return new ArrayList<>();
            }

            List<SimpleMediaItem> result = new ArrayList<>();

            Long userId = content.getUserId();
            ItemFilter<M> itemFilter = content.getItemFilter();
            for (M item : itemList) {
                if (itemFilter != null) {
                    if (itemFilter.needFilter() && itemFilter.setFlagThenGet(item)) {
                        continue;
                    }
                }
                SimpleMediaItem simpleMediaItem = content.transFor(item);
                result.add(simpleMediaItem);
            }

            if (withNext || content.hasNext()) {
                asyncGetItemList(content, (v) -> v.getExistUrls(url), cookiesSupplier);
            }

            cacheItemService.cacheMediaItemInfo(userId.toString(), result);
            queueService.addTask(new QueueService.BaseTask(result, (t) -> downLoadService.download((SimpleMediaItem) t)));

            return result;
        } catch (Exception e) {
            logger.error("get {}, content is empty[E]: {}", url, e);
            new RuntimeException(e.getMessage());
        }
        return new ArrayList<>();
    }

    private <T extends BaseDataInfo> void asyncGetItemList(T t, Function<T, List<String>> function, Supplier<String> cookiesSupplier) {
        List<String> urls = function.apply(t);
        queueService.addQueue(new QueueService.BaseTask(urls, v -> getItemList((String) v, false, t.getClass(), cookiesSupplier)));
    }

    public void setInitIdx(String id, long initIdx) {
        cacheItemService.setInitIdx(id, initIdx);
    }
}
